Zurück in DatenbankentwicklungWeiter in DatenbankentwicklungAnzeige kumulativer Notenhäufigkeiten ?

Das folgende Beispiel zeigt (ähnlich wie Formatierung von Zuordnungslösungen), dass sich die prozedurale Vorgehensweise manchmal besser eignet als die rein deklarative.

Benutzersicht

Die Trennung zwischen genügenden und ungenügenden Testleistungen fällt leichter, wenn die Verteilung der kumulierten Notenhäufigkeiten bekannt ist:

Entwurf

Die folgende Ereignisprozedur reagiert auf die Schaltfläche Kumulierte Noten des Formulars FrmNotenverteilung und erstellt als Datensatzherkunft die Tabelle TmpKUMULATIVE_NOTENHÄUFIGKEITEN für ein bereits definiertes Access-Balkendiagramms. Der folgende Entwurfscode besteht aus der Ereignisprozedur und einer Hilfsroutine:

Ereignisprozedur BtnKumulativeProzentualeNotenhäufigkeiten
  Ermittle für den laufenden Test die Notenzahl
  Ermittle für alle Noten absolute_Häufigkeiten
  Ermittle_kumulative_prozentuale_Häufigkeiten(Notenzahl, absolute_Häufigkeiten)
  Öffne das Access-Balkendiagramm
Ermittle_kumulative_prozentuale_Häufigkeiten(Notenzahl, absolute_Häufigkeiten)
  Kumulierte_absolute_Häufigkeit = 0
  Für alle einfachen absoluten Häufigkeiten
    Kumulierte_absolute_Häufigkeit = Kumulierte_absolute_Häufigkeit + absolute_Häufigkeit
    Kumulative_prozentuale_Häufigkeit = Kumulierte_absolute_Häufigkeit / Notenzahl
    Füge Note und deren kumulative_prozentuale_Häufigkeit zu TmpKUMULATIVE_NOTENHÄUFIGKEITEN

Implementation

Der Entwurfscode beschränkt sich auf die Verarbeitungslogik. Unter VBA und dem Objektmodell DAO kommen syntaktische und semantische Details hinzu, die das Verständnis erschweren.

'~~~ Datensatzherkunft TmpKUMULATIVE_NOTENHÄUFIGKEITEN des Balkendiagramms DrgNote erstellen
Private Sub BtnKumulativeProzentualeNotenhäufigkeiten_Click()
  '-- Recordset zur Zählung aller Noten des laufenden Tests
  Dim rstQryPteMCZOEssayLfTest_ohneNamen As Recordset
  Dim Notenzahl As Integer
  '-- Recordset der einfachen absoluten Notenhäufigkeiten des laufenden Tests
  Dim rstQryNotenhäufigkeiten As Recordset
  '-- Temporäre Tabelle der kumulierten prozentualen Notenhäufigkeiten (Datensatzherkunft von DgrNote)
  Dim tdf As TableDef
  Dim tdfTmpKUMULATIVE_NOTENHÄUFIGKEITEN As TableDef
  Dim rstTmpKUMULATIVE_NOTENHÄUFIGKEITEN As Recordset
  Dim KumulierteAbsoluteHäufigkeit As Integer
  '-- QueryDef-Objekt zur leichteren Verarbeitung geschachtelter Abfragen mit Parametern
  Dim qdf As QueryDef

  With CurrentDb

    'Ermittle für den laufenden Test die Notenzahl
    '---------------------------------------------
    Set qdf = .QueryDefs("QryPteMCZOEssayLfTest_ohneNamen")
    qdf.Parameters!parTestschlüssel = [Forms]![FrmNotenverteilung]![Testschlüssel]
    Set rstQryPteMCZOEssayLfTest_ohneNamen = qdf.OpenRecordset(dbReadOnly)
    '-- Balkendiagramm nur anzeigen, falls für den laufenden Test mindestens eine Note existiert
    If Not rstQryPteMCZOEssayLfTest_ohneNamen.EOF Then
      rstQryPteMCZOEssayLfTest_ohneNamen.MoveLast  'damit der folgende Befehl funktioniert
      Notenzahl = rstQryPteMCZOEssayLfTest_ohneNamen.RecordCount

      'Ermittle für alle Noten absolute_Häufigkeiten
      '---------------------------------------------
      Set qdf = .QueryDefs("QryNotenhäufigkeiten")
      'Der folgende Parameter nimmt zur  L a u f z e i t  den Testschlüssel auf
      qdf.Parameters!parTestschlüssel = [Forms]![FrmNotenverteilung]![Testschlüssel]
      Set rstQryNotenhäufigkeiten = qdf.OpenRecordset(dbOpenForwardOnly, dbReadOnly)

      'Ermittle für alle Noten kumulative prozentuale Häufigkeiten
      '-----------------------------------------------------------
      '-- Leere Tabelle und leerer Recordset für die kumulativen prozentualen Notenhäufigkeiten
      .TableDefs.Delete ("TmpKUMULATIVE_NOTENHÄUFIGKEITEN") 'falls vom letzten Aufruf her vorhanden
      Set tdfTmpKUMULATIVE_NOTENHÄUFIGKEITEN = .CreateTableDef("TmpKUMULATIVE_NOTENHÄUFIGKEITEN")
      With tdfTmpKUMULATIVE_NOTENHÄUFIGKEITEN
        .Fields.Append .CreateField("Note", dbSingle)
        .Fields.Append .CreateField("KumulativeProzentualeHäufigkeit", dbSingle)
      End With
      .TableDefs.Append tdfTmpKUMULATIVE_NOTENHÄUFIGKEITEN
      Set rstTmpKUMULATIVE_NOTENHÄUFIGKEITEN = .OpenRecordset("TmpKUMULATIVE_NOTENHÄUFIGKEITEN", dbOpenTable)

      '-- Prozentuale kumulative Notenhäufigkeiten satzweise aus den absoluten Häufigkeiten ermitteln
      With rstTmpKUMULATIVE_NOTENHÄUFIGKEITEN
        KumulierteAbsoluteHäufigkeit = 0
        Do Until rstQryNotenhäufigkeiten.EOF
          KumulierteAbsoluteHäufigkeit = KumulierteAbsoluteHäufigkeit + rstQryNotenhäufigkeiten!Notenhäufigkeit
          'Füge Note und deren kumulative prozentuale Häufigkeit an TmpKUMULATIVE_NOTENHÄUFIGKEITEN
          .AddNew
            !Note = rstQryNotenhäufigkeiten!Note
            !KumulativeProzentualeHäufigkeit = KumulierteAbsoluteHäufigkeit / Notenzahl
          .Update
          rstQryNotenhäufigkeiten.MoveNext
        Loop
        .Close  'Recordset als TmpKUMULATIVE_NOTENHÄUFIGKEITEN speichern
      End With
      Set rstTmpKUMULATIVE_NOTENHÄUFIGKEITEN = Nothing
      rstQryNotenhäufigkeiten.Close
      Set rstQryNotenhäufigkeiten = Nothing

      '-- Öffne das Access-Balkendiagramm
      DoCmd.OpenForm "FrmDrgKumulativeNotenhäufigkeiten"
    Else
      MsgBox "Ohne Noten kann kein Häufigkeitsdiagramm gezeichnet werden", vbOKOnly + vbExclamation, "Daten fehlen"
    End If
  End With 'CurrentDb
End Sub

Abfrageobjekte

Das Objekt QueryDef unterscheidet den obigen Code von den anderen Beispielen zur Satzverarbeitung. Die Themen DAO, Einzelsatzverarbeitung und Navigation durch Recordsets erstellen einen Recordset, indem sie dem DAO-Befehl OpenRecordset den Namen einer QBE-Abfrage oder den Wortlaut einer SQL-Anweisung übergeben:

Set Datensätze = laufendeDatenbank.OpenRecordset(<Abfrage>)

Die obige Ereignisprozedur BtnKumulativeProzentualeNotenhäufigkeiten_Click vereinbart hingegen eine Objektvariable qdf und weist ihr eine QBE-Abfrage zu:

Dim qdf As QueryDef
Set qdf = CurrentDb.QueryDefs("QryPteMCZOEssayLfTest_ohneNamen")

Auf das erzeugte Abfrageobjekt kann mit Eigenschaften und Methoden zugegriffen werden. Wenn die Abfrage zum Beispiel von einem zur Entwicklungszeit unbekannten Parameter abhängt, dann kann ihm das Programm zur Laufzeit einen Wert zuweisen:

qdf.Parameters!parTestschlüssel = [Forms]![FrmNotenverteilung]![Testschlüssel]

Oder die Abfrage kann zur Datensatzherkunft eines Recordset werden:

Set Datensätze = qdf.OpenRecordset(dbOpenForwardOnly, dbReadOnly)

Code, der auf explizite Abfrageobjekte verzichtet (grau markiert), ist zwar verständlicher, QueryDef-Objekte erleichtern aber die Verwaltung von Parametern und beschleunigen durch eine Kompilieren die Ausführung der Abfrage.